fb_extended_libfandomcom-20200215-history
UsingExtTemplates
The FreeBASIC Extended Library contains preprocessor APIs for the instantiation of templates, which are pieces of generic code in the form of user-defined macros. One (typical) benefit of templates is that they can minimize code duplication. For example, say that there is some procedure, an algorithm, that iterates through a range of elements in an array: ' Gets an iterator `it` to the first element in the range [first,last) for ' which `*it = value` is true, or `last` if there is no such element.function Find ( first as ubyte ptr, last as ubyte ptr, value as ubyte ) as byte ptr do while first < last if *first = value then exit do first += 1 loop return first end function An effective procedure, but it can only search through element ranges. If there is suddenly a need for a procedure with the same behavior and that works with element ranges, one option is to overload and define a second version: ' Gets an iterator `it` to the first element in the range (first,last) for ' which `*it = value` is true, or `last` if there is no such element.function Find overload ( first as ubyte ptr, last as ubyte ptr, value as ubyte ) as ubyte ptr do while first < last if *first = value then exit do first += 1 loop return first end function ' Gets an iterator `it` to the first element in the range [first,last) for ' which `*it = value` is true, or `last` if there is no such element. function Find ( first as integer ptr, last as integer ptr, value as integer ) as integer ptr do while first < last if *first = value then exit do first += 1 loop return first end function Notice how much code (and documentation!) is duplicated in this scenario. The only difference is in the signatures, which specify either or parameter types. To extend the functionality of to include ranges of other element types, typically the same code must be duplicated for each one. This is where a template can come in handy: #include once "ext/templates.bi" ' ElementType - the type of elements iterated through. #macro Find_Define( __, ElementType ): ' Gets an iterator `it` to the first element in the range [first,last) for ' which `*it = value` is true, or `last` if there is no such element. function Find overload ( first as fbext_TypeName(ElementType) ptr, _ last as fbext_TypeName(ElementType) ptr, _ value as fbext_TypeName(ElementType) _ ) as fbext_TypeName(ElementType) ptr do while first < last if *first = value then exit do first += 1 loop return first end function : #endmacro fbext_Instantiate( Find, ((ubyte)) ) fbext_Instantiate( Find, ((integer)) ) fbext_Instantiate( Find, ((double)) The new code begins by including the template header, which contains all of the macros used in the template system. Next, a macro is defined called which has two template parameters, the second of which is the type of elements that can iterate through, called . In order to specify this type, the macro is used in the parameter list. This macro translates the value of into something that can understand. Finally, the procedure template is instantiated with fbext_Instantiate, a macro which takes as a first argument the name of the template, in this case, Find. The second argument is a sequence of template arguments; one or more values enclosed in parenthesis, that will be passed to as template arguments. Here, the behavior of the last 3 lines is similar to: Find_Define( __, (ubyte) ) Find_Define( __, (integer) ) Find_Define( __, (double) ) with some stuff done behind the scenes. Thus, 3 Find overloads are defined, each that iterates through a different type of element, and with only 1 procedure definition. The procedure description comment has remained the same throughout the refactoring to emphasize the fact that the behavior has remained constant as well. Category:Tutorials Category:HasExamples Category:ExtTemplates